package com.projetIE.prudhomme_duisit.meteodata.listener;

/**
 * Please modify this class to meet your needs This class is not complete
 */

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.projetIE.prudhomme_duisit.meteodata.MeteoData;
import com.projetIE.prudhomme_duisit.meteodata.MeteoDataResponse;
import com.projetIE.prudhomme_duisit.meteodata.MeteoDataService;
import com.projetIE.prudhomme_duisit.meteodata.MeteoDataService_Service;
import com.projetIE.prudhomme_duisit.meteodata.Request;

/**
 * This class was generated by Apache CXF 2.1.4 Mon Oct 10 06:16:26 CEST 2011
 * Generated source version: 2.1.4
 * 
 */

public final class BpelReceiveListener implements MessageListener {
	
	private static final QName	SERVICE_NAME	= new QName(
	                                                 "http://www.projetIE.com/prudhomme_duisit/meteoData",
	                                                 "meteoDataService");
	
	private ConnectionFactory	connectionFactory;
	
	private Connection	       connection;
	
	private Destination	       destination;
	
	private Destination	       receive;
	
	private MeteoDataService	port;
	
	public static Logger	   LOG	         = Logger.getLogger(BpelReceiveListener.class);
	
	public BpelReceiveListener() {
		URL wsdlURL = MeteoDataService_Service.WSDL_LOCATION;
		MeteoDataService_Service ss = new MeteoDataService_Service(wsdlURL, SERVICE_NAME);
		port = ss.getMeteoDataServiceSOAP();
		connect();
		initReceiveListener();
	}
	
	private void connect() {
		Context jndiContext;
		try {
			jndiContext = new InitialContext();
			connectionFactory = (ConnectionFactory) jndiContext.lookup("connectionFactory");
			destination = (Destination) jndiContext.lookup("responseQueue");
			receive = (Destination) jndiContext.lookup("requestQueue");
			connection = connectionFactory.createConnection();
		} catch (NamingException e) {
			LOG.error("Naming exception : connection failed");
			e.printStackTrace();
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException a) {
				}
			}
			System.exit(1);
		} catch (JMSException e) {
			LOG.error("JMS error : connection failed");
			e.printStackTrace();
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException a) {
				}
			}
		}
		
	}
	
	private void initReceiveListener() {
		try {
			Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			MessageConsumer consumer = session.createConsumer(receive);
			
			consumer.setMessageListener(this);
			connection.start();
		} catch (JMSException e) {
			LOG.error("JMS error : Listener not initate");
			e.printStackTrace();
			if (connection != null) {
				try {
					connection.close();
				} catch (JMSException a) {
				}
			}
		}
	}
	
	public void onMessage(Message message) {
		try {
			if (message instanceof TextMessage) {
				String msgText = ((TextMessage) message).getText();
				Document doc = stringToDom(msgText);
				LOG.info("invocking meteoData with : " + msgText);
				{
					Request req = new Request();
					
					NodeList List = doc.getElementsByTagName("client");
					if (List.getLength() != 0) {
						req.setClient(List.item(0).getTextContent());
						java.lang.String _meteoData_pays = null;
						java.lang.String _meteoData_ville = null;
						List = doc.getElementsByTagName("pays");
						if (List.getLength() != 0) {
							req.setPays(List.item(0).getTextContent());
						}
						List = doc.getElementsByTagName("ville");
						if (List.getLength() != 0) {
							req.setVille(List.item(0).getTextContent());
						}
						com.projetIE.prudhomme_duisit.meteodata.MeteoData _meteoData_parameters = new MeteoData();
						
						_meteoData_parameters.setRequest(req);
						MeteoDataResponse rep = port.meteoData(_meteoData_parameters);
						if (rep.getResponse().getReponseMeteo().getMeteo().getLieu()
						        .equals("Data not found")) {
							rep.getResponse().getReponseMeteo().getMeteo().setLieu("");
						} else {
							MeteoDataResponse response = parse(rep);
						}
						LOG.info("parsing done...");
						sendMessages(rep);
					}
					
				}
			}
		} catch (JMSException jmse) {
			LOG.error("JMS error : message not received properly");
			jmse.printStackTrace();
		} catch (SAXException e) {
			LOG.error("Parsing error : message not well formed");
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			LOG.error("Parsing error : configuration not well setted");
			e.printStackTrace();
		} catch (IOException e) {
			LOG.error("I/O error : message not received properly");
			e.printStackTrace();
		}
	}
	
	protected static Document stringToDom(String xmlSource) throws SAXException,
	        ParserConfigurationException, IOException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		return builder.parse(new ByteArrayInputStream(xmlSource.getBytes("UTF-8")));
	}
	
	protected static String domToString(final Document _document) throws TransformerException {
		TransformerFactory tFactory = TransformerFactory.newInstance();
		Transformer transformer = tFactory.newTransformer();
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		DOMSource source = new DOMSource(_document);
		StringWriter sw = new StringWriter();
		StreamResult result = new StreamResult(sw);
		transformer.transform(source, result);
		return sw.toString();
	}
	
	private boolean sendMessages(MeteoDataResponse p) {
		
		boolean success = true;
		try {
			Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			MessageProducer producer = session.createProducer(destination);
			TextMessage message = session.createTextMessage(domToString(p.generatedDom()));
			producer.send(message);
		} catch (JMSException e) {
			LOG.error("JMS error : message not send");
			e.printStackTrace();
			success = false;
		} catch (TransformerException e) {
			LOG.error("Transformer error : message not send");
			e.printStackTrace();
			success = false;
		}
		
		return success;
	}
	
	private static MeteoDataResponse parse(MeteoDataResponse p) {
		
		String value = new String(p.getResponse().getReponseMeteo().getMeteo().getLieu());
		p.getResponse().getReponseMeteo().getMeteo()
		        .setDateHeure(parseAccordingTo(value, "<Time>", "</Time>"));
		LOG.info(p.getResponse().getReponseMeteo().getMeteo().getDateHeure());
		
		p.getResponse().getReponseMeteo().getMeteo()
		        .setVent(parseAccordingTo(value, "<Wind>", "</Wind>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setVisibilite(parseAccordingTo(value, "<Visibility>", "</Visibility>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setCiel(parseAccordingTo(value, "<SkyConditions>", "</SkyConditions>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setTemperature(parseAccordingTo(value, "<Temperature>", "</Temperature>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setPointRosee(parseAccordingTo(value, "<DewPoint>", "</DewPoint>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setHumidite(parseAccordingTo(value, "<RelativeHumidity>", "</RelativeHumidity>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setPression(parseAccordingTo(value, "<Pressure>", "</Pressure>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setStatus(parseAccordingTo(value, "<Status>", "</Status>"));
		p.getResponse().getReponseMeteo().getMeteo()
		        .setLieu(parseAccordingTo(value, "<Location>", "</Location>"));
		return p;
	}
	
	private static String parseAccordingTo(String in, String start, String end) {
		String resul = "";
		if (in.indexOf(start) + start.length() >= 0) {
			if (in.indexOf(end) >= 0) {
				resul = in.substring(in.indexOf(start) + start.length(), in.indexOf(end));
			}
		}
		return resul;
		
	}
}
